package top.yqingyu.trans$client.main;

import top.yqingyu.common.utils.ThreadUtil;
import top.yqingyu.qymsg.Dict;
import top.yqingyu.qymsg.QyMsg;
import top.yqingyu.qymsg.bean.StringKey;
import top.yqingyu.trans$client.api.Connection;
import top.yqingyu.trans$client.api.ConnectionConfig;
import top.yqingyu.trans$client.exception.CreateTransClientUnsuccessful;

import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author YYJ
 * @version 1.0.0
 * @ClassName top.yqingyu.transclient.main.ClientAPI
 * @description
 * @createTime 2023年01月08日 17:49:00
 */
public class ClientAPI {

    private final TransClient client;
    private boolean isSync = false;

    private final ThreadPoolExecutor executor = ThreadUtil.createQyFixedThreadPool(Math.max(2, Runtime.getRuntime().availableProcessors() / 2), "Message", "th");


    private ClientAPI(ConnectionConfig config) throws Exception {
        this.client = new TransClient(config);
    }

    public static ClientAPI initSync(ConnectionConfig config) throws Exception {
        try {
            ClientAPI api = new ClientAPI(config);
            System.setProperty(api.client.clientConf.CLIENT_USER_ID, "API");
            api.isSync = true;
            HeartBeatThread.init(api.client);
            SendMsgThread.init(api.client);
            return api;
        } catch (Exception e) {
            throw new CreateTransClientUnsuccessful("客户端创建失败", e);
        }

    }

    public static ClientAPI initAsync(ConnectionConfig config) throws Exception {
        try {
            ClientAPI api = new ClientAPI(config);
            System.setProperty(api.client.clientConf.CLIENT_USER_ID, "API");
            HeartBeatThread.init(api.client);
            SendMsgThread.init(api.client);
            ReadMsgThread.init(api.client);
            return api;
        } catch (Exception e) {
            throw new CreateTransClientUnsuccessful("客户端创建失败", e);
        }

    }

    public static TransClient initClient(ConnectionConfig config) throws Exception {
        return new TransClient(config);
    }

    public void shutdown() throws InterruptedException, CloneNotSupportedException {
        client.running.set(false);
        QyMsg clone = client.clientConf.NORMAL_MSG.clone();
        clone.putMsg("quit");
        //关闭发送线程
        client.REQ_MSG_QUEUE.put(clone);
        executor.shutdown();
    }

    public TransClient getClient() {
        return client;
    }

    public QyMsg send(QyMsg msg) throws Exception {
        if (isSync) {
            Connection connection = client.getConnection();
            try {
                connection.lock.lock();
                DealMsgThread dealMsgThread = new DealMsgThread(msg, connection, client);
                dealMsgThread.run();
                return connection.receive();
            } finally {
                connection.lock.unlock();
            }
        }
        String genMsgId = msg.genMsgId();
        client.REQ_MSG_QUEUE.put(msg);
        AtomicBoolean arun = new AtomicBoolean(true);
        FutureTask<QyMsg> task = new FutureTask<>(() -> {
            while (arun.get()) {
                QyMsg ms = client.RCV_MSG_CONTAINER.remove(genMsgId);
                if (ms != null) {
                    return ms;
                }
            }
            return null;
        });
        Thread th = new Thread(task);
        th.setName(Thread.currentThread().getName());
        executor.execute(th);
        QyMsg qyMsg;
        try {
            qyMsg = task.get(3000, TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            qyMsg = null;
        }
        arun.set(false);
        return qyMsg;
    }


    public QyMsg makeStrKey(StringKey strKey) {
        QyMsg qyMsg = client.clientConf.NORMAL_MSG.clone().putMsgData(Dict.KEY_CMD, strKey);
        qyMsg.putMsg(Dict.KEY_CMD);
        return qyMsg;
    }
}
